﻿using MIO.Client.Util;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

namespace MIO.Client.Ack
{
    public class AckReceiveTask
    {
        private readonly ConcurrentDictionary<String, long> ackId2Timestamp = new ConcurrentDictionary<String, long>();
        private Timer timer = null;
        private IOClient client;
        private int ackTimeout = 3;
        private int checkInterval = 0;

        public AckReceiveTask(IOClient client)
        {
            this.client = client;
            this.ackTimeout = client.Config.AckTimeout;
            checkInterval = ackTimeout * 100000;
        }

        private void doTaskOnece()
        {
            foreach (var item in ackId2Timestamp)
            {
                String key = item.Key;
                long value = item.Value;
                long delta = DateUtil.GetCurrentTimeStamp() - value;
                if (delta >= checkInterval)
                {
                    long discard = 0;
                    ackId2Timestamp.TryRemove(key, out discard);
                }
            }

        }


        public AckReceiveTask startup(bool immediately)
        {
            stop();

            timer = new Timer();
            timer.Interval = immediately ? 1 : checkInterval;
            timer.Elapsed += (sender, e) =>
            {
                doTaskOnece();
            };
            timer.Start();
            return this;
        }

        public void stop()
        {
            if (timer != null)
            {
                try
                {
                    timer.Stop();
                }
                finally
                {
                    timer = null;
                }
            }
        }

        public bool isRunning()
        {
            return timer != null;
        }
         
        public void put(String ackId)
        {
            if (!ackId2Timestamp.ContainsKey(ackId))
                ackId2Timestamp.TryAdd(ackId, DateUtil.GetCurrentTimeStamp());
        }

        public bool hasRecieved(String ackId)
        {
            return ackId2Timestamp.ContainsKey(ackId);
        }
    }
}